// go运行gen.go生成的代码；不要编辑。

package imageutil

import (
	"image"
)

// DrawYCbCr使用
// /r.Min在dst中与src中的sp对齐，在RGBA目标映像上绘制YCbCr源映像。它报告了抽签是否成功。如果返回false，则未更改dst像素。
// 
// 此函数假定r完全在dst的范围内，并且
// r从dst坐标空间到src坐标空间的转换是
// 完全在src的范围内。
func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) (ok bool) {
	// 此函数存在于image/internal/imageutil包中，因为它
	// 是image/draw和image/jpeg包都需要的，但这两个包中的一个依赖于另一个似乎不正确。
	// 
	// 另一种选择是将此代码导出到映像包中，
	// 但是我们需要确保我们对API完全满意（对于
	// Go 1的其他兼容性），然后决定我们是否希望对其他图像类型使用更
	// 通用DrawToRGBA方法。一种可能性是：
	// 
	// 
	// func（src*YCbCr）CopyToRGBA（dst*RGBA，dr，sr矩形）（effectiveDr，effectiveSr矩形）
	// 
	// ，
	// 如果需要，还允许使用CopyFromRGBA方法。

	x0 := (r.Min.X - dst.Rect.Min.X) * 4
	x1 := (r.Max.X - dst.Rect.Min.X) * 4
	y0 := r.Min.Y - dst.Rect.Min.Y
	y1 := r.Max.Y - dst.Rect.Min.Y
	switch src.SubsampleRatio {

	case image.YCbCrSubsampleRatio444:
		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride:]
			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)

			ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X)
			for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {

				// 这是image/color/ycbcr.go函数YCbCrToRGB的内联版本。
				yy1 := int32(src.Y[yi]) * 0x10101
				cb1 := int32(src.Cb[ci]) - 128
				cr1 := int32(src.Cr[ci]) - 128

				// 下面的位旋转相当于
				// 
				// r:=（yy1+91881*cr1）>>16 
				// 如果r<0{
				// /r=0 
				// /}如果r>0xff{
				// /r=^int32（0）
				// /}
				// 
				// 但使用的分支更少，速度更快。
				// 注意，返回
				// 语句中的uint8类型转换将^int32（0）转换为0xff。
				// 下面计算g和b的代码使用类似的模式。
				r := yy1 + 91881*cr1
				if uint32(r)&0xff000000 == 0 {
					r >>= 16
				} else {
					r = ^(r >> 31)
				}

				g := yy1 - 22554*cb1 - 46802*cr1
				if uint32(g)&0xff000000 == 0 {
					g >>= 16
				} else {
					g = ^(g >> 31)
				}

				b := yy1 + 116130*cb1
				if uint32(b)&0xff000000 == 0 {
					b >>= 16
				} else {
					b = ^(b >> 31)
				}

				// 使用一个临时切片来提示编译器，一个边界检查就足够了
				rgba := dpix[x : x+4 : len(dpix)]
				rgba[0] = uint8(r)
				rgba[1] = uint8(g)
				rgba[2] = uint8(b)
				rgba[3] = 255
			}
		}

	case image.YCbCrSubsampleRatio422:
		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride:]
			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)

			ciBase := (sy-src.Rect.Min.Y)*src.CStride - src.Rect.Min.X/2
			for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
				ci := ciBase + sx/2

				// 这是image/color/ycbcr.go的func-YCbCrToRGB的内联版本。
				yy1 := int32(src.Y[yi]) * 0x10101
				cb1 := int32(src.Cb[ci]) - 128
				cr1 := int32(src.Cr[ci]) - 128

				// 下面的位旋转相当于
				// 
				// r:=（yy1+91881*cr1）>>16 
				// 如果r<0{
				// /r=0 
				// /}如果r>0xff{
				// /r=^int32（0）
				// /}
				// 
				// 但使用的分支更少，速度更快。
				// 注意，返回
				// 语句中的uint8类型转换将^int32（0）转换为0xff。
				// 下面计算g和b的代码使用类似的模式。
				r := yy1 + 91881*cr1
				if uint32(r)&0xff000000 == 0 {
					r >>= 16
				} else {
					r = ^(r >> 31)
				}

				g := yy1 - 22554*cb1 - 46802*cr1
				if uint32(g)&0xff000000 == 0 {
					g >>= 16
				} else {
					g = ^(g >> 31)
				}

				b := yy1 + 116130*cb1
				if uint32(b)&0xff000000 == 0 {
					b >>= 16
				} else {
					b = ^(b >> 31)
				}

				// 使用一个临时切片向编译器提示一个边界检查就足够了
				rgba := dpix[x : x+4 : len(dpix)]
				rgba[0] = uint8(r)
				rgba[1] = uint8(g)
				rgba[2] = uint8(b)
				rgba[3] = 255
			}
		}

	case image.YCbCrSubsampleRatio420:
		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride:]
			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)

			ciBase := (sy/2-src.Rect.Min.Y/2)*src.CStride - src.Rect.Min.X/2
			for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
				ci := ciBase + sx/2

				// 这是image/color/ycbcr.go函数YCbCrToRGB的内联版本。
				yy1 := int32(src.Y[yi]) * 0x10101
				cb1 := int32(src.Cb[ci]) - 128
				cr1 := int32(src.Cr[ci]) - 128

				// 下面的位旋转相当于
				// 
				// r:=（yy1+91881*cr1）>>16 
				// 如果r<0{
				// /r=0 
				// /}如果r>0xff{
				// /r=^int32（0）
				// 
				// 但使用的分支更少，速度更快。
				// 注意，返回
				// 语句中的uint8类型转换将^int32（0）转换为0xff。
				// 下面计算g和b的代码使用类似的模式。
				r := yy1 + 91881*cr1
				if uint32(r)&0xff000000 == 0 {
					r >>= 16
				} else {
					r = ^(r >> 31)
				}

				g := yy1 - 22554*cb1 - 46802*cr1
				if uint32(g)&0xff000000 == 0 {
					g >>= 16
				} else {
					g = ^(g >> 31)
				}

				b := yy1 + 116130*cb1
				if uint32(b)&0xff000000 == 0 {
					b >>= 16
				} else {
					b = ^(b >> 31)
				}

				// 使用一个临时切片来提示编译器，一个边界检查就足够了
				rgba := dpix[x : x+4 : len(dpix)]
				rgba[0] = uint8(r)
				rgba[1] = uint8(g)
				rgba[2] = uint8(b)
				rgba[3] = 255
			}
		}

	case image.YCbCrSubsampleRatio440:
		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride:]
			yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)

			ci := (sy/2-src.Rect.Min.Y/2)*src.CStride + (sp.X - src.Rect.Min.X)
			for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {

				// 这是image/color/ycbcr.go函数YCbCrToRGB的内联版本。
				yy1 := int32(src.Y[yi]) * 0x10101
				cb1 := int32(src.Cb[ci]) - 128
				cr1 := int32(src.Cr[ci]) - 128

				// 下面的位旋转相当于
				// 
				// r:=（yy1+91881*cr1）>>16 
				// 如果r<0{
				// /r=0 
				// /}如果r>0xff{
				// /r=^int32（0）
				// 
				// 但使用的分支更少，速度更快。
				// 注意，返回
				// 语句中的uint8类型转换将^int32（0）转换为0xff。
				// 下面计算g和b的代码使用类似的模式。
				r := yy1 + 91881*cr1
				if uint32(r)&0xff000000 == 0 {
					r >>= 16
				} else {
					r = ^(r >> 31)
				}

				g := yy1 - 22554*cb1 - 46802*cr1
				if uint32(g)&0xff000000 == 0 {
					g >>= 16
				} else {
					g = ^(g >> 31)
				}

				b := yy1 + 116130*cb1
				if uint32(b)&0xff000000 == 0 {
					b >>= 16
				} else {
					b = ^(b >> 31)
				}

				// 使用一个临时切片来提示编译器，一个边界检查就足够了
				rgba := dpix[x : x+4 : len(dpix)]
				rgba[0] = uint8(r)
				rgba[1] = uint8(g)
				rgba[2] = uint8(b)
				rgba[3] = 255
			}
		}

	default:
		return false
	}
	return true
}
